
#include "circuit_board.h"
#include <stdint.h>
#include "driver/rmt_encoder.h"
#include "my_led_strip.h"
#include "driver/rmt_tx.h"
#include "esp_check.h"
#include "led_strip_encoder.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <math.h>
#include <driver/gpio.h>


const uint16_t indexWave[] = {1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 22, 25, 28, 32, 36, 41, 47, 53, 61, 69, 79, 89, 102, 116, 131, 149, 170, 193, 219, 250, 284, 323, 367, 417, 474, 539, 613, 697, 792, 901, 1023, 1023, 1023, 1023, 1023, 1023, 901, 792, 697, 613, 539, 474, 417, 367, 323, 284, 250, 219, 193, 170, 149, 131, 116, 102, 89, 79, 69, 61, 53, 47, 41, 36, 32, 28, 25, 22, 19, 17, 15, 13, 11, 10, 9, 8, 7, 6, 5, 5, 4, 4, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1};
static const char *TAG = "my_led_strip";

static float breath_index = 0;  // 用于表示当前的呼吸周期位置
const float breath_speed = 0.01;  // 呼吸速度调整参数
const float min_brightness = 0.0;  // 亮度最低可设置为 0
const float max_brightness = 1.0;  // 最大亮度

int RUNNING_LED_NUMBER = 3; // 循环灯的数量
int R_COLOR = 0x3f;         // Range [0:0xff]  hex
int G_COLOR = 0x00;         // Range [0:0xff]  hex
int B_COLOR = 0x00;         // Range [0:0xff]  hex
int BREATH_R_COLOR = 0x00;  //
int BREATH_G_COLOR = 0x00;  //
int BREATH_B_COLOR = 0x3f;  //
int RUNNING_R_COLOR = 0x00; //
int RUNNING_G_COLOR = 0x3F; //4
int RUNNING_B_COLOR = 0x00; //
int RUNNING_DELAY = 200;    //  running interval 200ms the bigger the slower
int BREATHING_DELAY = 20;   // 50ms the bigger the slower
int led_delay = 1;
int LED_WAKEUP_FLAG = 1;
int led_state = LED_OFF;
int specific_led[STRIP_LED_NUMBER] = {0};
int running_index = 0;
int breathing_index = 0;

uint8_t led_strip_pixels[STRIP_LED_NUMBER * 3];
rmt_channel_handle_t led_chan = NULL;
rmt_transmit_config_t tx_config;
rmt_encoder_handle_t led_encoder = NULL;

void ledstrip_init(void)
{

    rmt_tx_channel_config_t tx_chan_config = {
        .gpio_num = RMT_TX_GPIO,
        .clk_src = RMT_CLK_SRC_DEFAULT, // select source clock
        .resolution_hz = 10000000,
        .mem_block_symbols = 64, // increase the block size can make the LED less flickering
        .trans_queue_depth = 4,  // set the number of transactions that can be pending in the background
    };
    ESP_ERROR_CHECK(rmt_new_tx_channel(&tx_chan_config, &led_chan));

    ESP_LOGI(TAG, "Install led strip encoder");
    led_strip_encoder_config_t encoder_config = {
        .resolution = 10000000,
    };
    ESP_ERROR_CHECK(rmt_new_led_strip_encoder(&encoder_config, &led_encoder));

    ESP_LOGI(TAG, "Enable RMT TX channel");
    ESP_ERROR_CHECK(rmt_enable(led_chan));

    ESP_LOGI(TAG, "Start LED rainbow chase");
    tx_config.loop_count = 0; // no transfer loop

    memset(led_strip_pixels, 0, sizeof(led_strip_pixels));
    ESP_ERROR_CHECK(rmt_transmit(led_chan, led_encoder, led_strip_pixels, sizeof(led_strip_pixels), &tx_config));
    ESP_ERROR_CHECK(rmt_tx_wait_all_done(led_chan, portMAX_DELAY));

    for (int i = 0; i < STRIP_LED_NUMBER; i++)
    {
        led_strip_pixels[i * 3 + 0] = G_COLOR;
        led_strip_pixels[i * 3 + 1] = 0xff;
        led_strip_pixels[i * 3 + 2] = 0xff;
    }

    rmt_transmit(led_chan, led_encoder, led_strip_pixels, sizeof(led_strip_pixels), &tx_config);
    ESP_ERROR_CHECK(rmt_tx_wait_all_done(led_chan, portMAX_DELAY));
}
void led_clear_all(void)
{
    memset(led_strip_pixels, 0, sizeof(led_strip_pixels));
    ESP_ERROR_CHECK(rmt_transmit(led_chan, led_encoder, led_strip_pixels, sizeof(led_strip_pixels), &tx_config));
    ESP_ERROR_CHECK(rmt_tx_wait_all_done(led_chan, portMAX_DELAY));
}
void led_clear_all_array(void)
{
    memset(led_strip_pixels, 0, sizeof(led_strip_pixels));
}
void led_task(void *para)
{
    ledstrip_init();
    while (1)
    {
        //        ESP_LOGI(TAG, "nowLED_WAKEUP_FLAG :%d-----%d", LED_WAKEUP_FLAG, led_state);
        if (LED_WAKEUP_FLAG == 1) // 1是对话时
        {

            switch (led_state)
            {
            case LED_ON:
                for (int i = 0; i < STRIP_LED_NUMBER; i++)
                {
                    led_strip_pixels[i * 3 + 0] = G_COLOR;
                    led_strip_pixels[i * 3 + 1] = R_COLOR;
                    led_strip_pixels[i * 3 + 2] = B_COLOR;
                }

                rmt_transmit(led_chan, led_encoder, led_strip_pixels, sizeof(led_strip_pixels), &tx_config);
                break;
            case LED_BREATH:
                while (LED_BREATH == led_state)
                {
                    /*for (int i = 0; i < STRIP_LED_NUMBER; i++)
                    {
                        led_strip_pixels[i * 3 + 0] = BREATH_G_COLOR * indexWave[breathing_index] / 1024;
                        led_strip_pixels[i * 3 + 1] = BREATH_R_COLOR * indexWave[breathing_index] / 1024;
                        led_strip_pixels[i * 3 + 2] = BREATH_B_COLOR * indexWave[breathing_index] / 1024;
                    }

                    breathing_index++;
                    if (breathing_index > 111)
                        breathing_index = 0;

                    vTaskDelay(BREATHING_DELAY);*/

                    // 正弦函数生成亮度，范围 [0, 1]
                    float brightness = (sin(breath_index * M_PI) + 1) / 2;

                    // 对低亮度部分进行进一步压缩，使其更接近 0
                    if (brightness < 0.2) {
                        brightness = pow(brightness, 3);  // 对低亮度做指数压缩，加速衰减
                    }

                    // 调整亮度范围 [min_brightness, max_brightness]
                    brightness = brightness * (max_brightness - min_brightness) + min_brightness;

                    // 设置 LED 颜色
                    for (int i = 0; i < STRIP_LED_NUMBER; i++) {
                        led_strip_pixels[i * 3 + 0] = BREATH_G_COLOR * brightness;
                        led_strip_pixels[i * 3 + 1] = BREATH_R_COLOR * brightness;
                        led_strip_pixels[i * 3 + 2] = BREATH_B_COLOR * brightness;
                    }

                    breath_index += breath_speed;
                    if (breath_index > 1) {
                        breath_index = 0;  // 完成一个周期后重置
                    }

                    vTaskDelay(BREATHING_DELAY);  // 控制每次亮度变化的速度

                    ESP_ERROR_CHECK(rmt_transmit(led_chan, led_encoder, led_strip_pixels, sizeof(led_strip_pixels), &tx_config));
                    ESP_ERROR_CHECK(rmt_tx_wait_all_done(led_chan, portMAX_DELAY));
                }
                break;
            case LED_RUNNING:
                while (LED_RUNNING == led_state)
                {

                    led_clear_all_array();
                    for (int d = 0; d < 0 + RUNNING_LED_NUMBER; d++)
                    {
                        led_strip_pixels[((running_index + d) % STRIP_LED_NUMBER) * 3 + 0] = RUNNING_G_COLOR;
                        led_strip_pixels[((running_index + d) % STRIP_LED_NUMBER) * 3 + 1] = RUNNING_R_COLOR;
                        led_strip_pixels[((running_index + d) % STRIP_LED_NUMBER) * 3 + 2] = RUNNING_B_COLOR;
                    }
                    running_index++;
                    if (running_index > STRIP_LED_NUMBER - 1)
                        running_index = 0;
                    vTaskDelay(RUNNING_DELAY);
                    ESP_ERROR_CHECK(rmt_transmit(led_chan, led_encoder, led_strip_pixels, sizeof(led_strip_pixels), &tx_config));
                    ESP_ERROR_CHECK(rmt_tx_wait_all_done(led_chan, portMAX_DELAY));
                }
                break;
            case LED_OFF:
                led_clear_all_array();

                breathing_index = 0;
                led_state = LED_IDLE;
                break;
            case LED_WAITTING_BREATH:
                while (LED_WAITTING_BREATH == led_state)
                {
                    for (int i = 0; i < STRIP_LED_NUMBER; i++)
                    {
                        led_strip_pixels[i * 3 + 0] = WAITTING_G_COLOR * indexWave[breathing_index] / 1024;
                        led_strip_pixels[i * 3 + 1] = WAITTING_R_COLOR * indexWave[breathing_index] / 1024;
                        led_strip_pixels[i * 3 + 2] = WAITTING_B_COLOR * indexWave[breathing_index] / 1024;
                    }

                    breathing_index++;
                    if (breathing_index > 111)
                        breathing_index = 0;

                    vTaskDelay(BREATHING_DELAY);
                    ESP_ERROR_CHECK(rmt_transmit(led_chan, led_encoder, led_strip_pixels, sizeof(led_strip_pixels), &tx_config));
                    ESP_ERROR_CHECK(rmt_tx_wait_all_done(led_chan, portMAX_DELAY));
                }
                break;
            default:
                break;
            }
        }
        else
        {
            switch (led_state)
            {
            case LED_OFF:
                led_clear_all_array();

                breathing_index = 0;
                break;
            case LED_ON_SPEC:
                vTaskDelay(led_delay);
                led_clear_all_array();

                for (int i = 0; i < STRIP_LED_NUMBER; i++)
                {

                    if (specific_led[i] != -1)
                    {
                        led_strip_pixels[specific_led[i] * 3 + 0] = G_COLOR;
                        led_strip_pixels[specific_led[i] * 3 + 1] = R_COLOR;
                        led_strip_pixels[specific_led[i] * 3 + 2] = B_COLOR;
                    }
                }

                break;
            case LED_BREATH_SPEC:
                vTaskDelay(led_delay);
                while (LED_BREATH_SPEC == led_state)
                {
                    for (int i = 0; i < STRIP_LED_NUMBER; i++)
                    {
                        if (specific_led[i] != -1)
                        {
                            led_strip_pixels[specific_led[i] * 3 + 0] = BREATH_G_COLOR * indexWave[breathing_index] / 1024;
                            led_strip_pixels[specific_led[i] * 3 + 1] = BREATH_R_COLOR * indexWave[breathing_index] / 1024;
                            led_strip_pixels[specific_led[i] * 3 + 2] = BREATH_B_COLOR * indexWave[breathing_index] / 1024;
                        }
                    }

                    breathing_index++;
                    if (breathing_index > 111)
                        breathing_index = 0;

                    vTaskDelay(BREATHING_DELAY);
                    ESP_ERROR_CHECK(rmt_transmit(led_chan, led_encoder, led_strip_pixels, sizeof(led_strip_pixels), &tx_config));
                    ESP_ERROR_CHECK(rmt_tx_wait_all_done(led_chan, portMAX_DELAY));
                }
                break;
            case LED_RUNNING_SPEC:
                vTaskDelay(led_delay);
                while (LED_RUNNING_SPEC == led_state)
                {
                    led_clear_all_array();
                    for (int d = 0; d < 0 + RUNNING_LED_NUMBER; d++)
                    {
                        led_strip_pixels[((running_index + d) % STRIP_LED_NUMBER) * 3 + 0] = RUNNING_G_COLOR;
                        led_strip_pixels[((running_index + d) % STRIP_LED_NUMBER) * 3 + 1] = RUNNING_R_COLOR;
                        led_strip_pixels[((running_index + d) % STRIP_LED_NUMBER) * 3 + 2] = RUNNING_B_COLOR;
                    }
                    running_index++;
                    if (running_index > STRIP_LED_NUMBER - 1)
                        running_index = 0;

                    vTaskDelay(RUNNING_DELAY);
                    ESP_ERROR_CHECK(rmt_transmit(led_chan, led_encoder, led_strip_pixels, sizeof(led_strip_pixels), &tx_config));
                    ESP_ERROR_CHECK(rmt_tx_wait_all_done(led_chan, portMAX_DELAY));
                }
                break;
            case LED_OFF_SPEC:
                vTaskDelay(led_delay);
                for (int i = 0; i < STRIP_LED_NUMBER; i++)
                {
                    if (specific_led[i] != -1)
                    {
                        led_strip_pixels[specific_led[i] * 3 + 0] = 0;
                        led_strip_pixels[specific_led[i] * 3 + 1] = 0;
                        led_strip_pixels[specific_led[i] * 3 + 2] = 0;
                    }
                }

                break;
            case LED_SHAN_ON_SPEC:
                vTaskDelay(led_delay);
                for (int t = 0; t < 3; t++)
                {

                    for (int i = 0; i < STRIP_LED_NUMBER; i++)
                    {
                        if (specific_led[i] != -1)
                        {
                            led_strip_pixels[specific_led[i] * 3 + 0] = G_COLOR;
                            led_strip_pixels[specific_led[i] * 3 + 1] = R_COLOR;
                            led_strip_pixels[specific_led[i] * 3 + 2] = B_COLOR;
                        }
                    }

                    vTaskDelay(150);
                    for (int i = 0; i < STRIP_LED_NUMBER; i++)
                    {
                        if (specific_led[i] != -1)
                        {
                            led_strip_pixels[specific_led[i] * 3 + 0] = 0;
                            led_strip_pixels[specific_led[i] * 3 + 1] = 0;
                            led_strip_pixels[specific_led[i] * 3 + 2] = 0;
                        }
                    }

                    vTaskDelay(150);
                }
                for (int i = 0; i < STRIP_LED_NUMBER; i++)
                {
                    if (specific_led[i] != -1)
                    {
                        led_strip_pixels[specific_led[i] * 3 + 0] = G_COLOR;
                        led_strip_pixels[specific_led[i] * 3 + 1] = R_COLOR;
                        led_strip_pixels[specific_led[i] * 3 + 2] = B_COLOR;
                    }
                }

                led_state = LED_IDLE;
                break;
            case LED_SHAN_OFF_SPEC:
                vTaskDelay(led_delay);
                for (int t = 0; t < 3; t++)
                {

                    for (int i = 0; i < STRIP_LED_NUMBER; i++)
                    {
                        if (specific_led[i] != -1)
                        {
                            led_strip_pixels[specific_led[i] * 3 + 0] = G_COLOR;
                            led_strip_pixels[specific_led[i] * 3 + 1] = R_COLOR;
                            led_strip_pixels[specific_led[i] * 3 + 2] = B_COLOR;
                        }
                    }

                    vTaskDelay(150);
                    for (int i = 0; i < STRIP_LED_NUMBER; i++)
                    {
                        if (specific_led[i] != -1)
                        {
                            led_strip_pixels[specific_led[i] * 3 + 0] = 0;
                            led_strip_pixels[specific_led[i] * 3 + 1] = 0;
                            led_strip_pixels[specific_led[i] * 3 + 2] = 0;
                        }
                    }

                    vTaskDelay(150);
                }
                for (int i = 0; i < STRIP_LED_NUMBER; i++)
                {
                    if (specific_led[i] != -1)
                    {
                        led_strip_pixels[specific_led[i] * 3 + 0] = 0;
                        led_strip_pixels[specific_led[i] * 3 + 1] = 0;
                        led_strip_pixels[specific_led[i] * 3 + 2] = 0;
                    }
                }

                led_state = LED_IDLE;
                break;
                //                case LED_RAINBOW:
                //                    while (LED_RAINBOW == led_state)
                //                    {
                //                        for (int i = 0; i < STRIP_LED_NUMBER; i++)
                //                        {
                //                            uint8_t r, g, b;
                //                            float position = (float)(i + running_index) / (float)STRIP_LED_NUMBER;
                //                            r = (uint8_t)(sin(position * 2 * M_PI) * 127 + 128);
                //                            g = (uint8_t)(sin(position * 2 * M_PI + 2 * M_PI / 3) * 127 + 128);
                //                            b = (uint8_t)(sin(position * 2 * M_PI + 4 * M_PI / 3) * 127 + 128);
                //                            ESP_ERROR_CHECK(strip->set_pixel(strip, i, r, g, b));
                //                        }
                //                        running_index++;
                //                        if (running_index >= STRIP_LED_NUMBER)
                //                            running_index = 0;
                //                        ESP_ERROR_CHECK(strip->refresh(strip, 100));
                //                        vTaskDelay(100);
                //                    }
                //                    break;
            case LED_IDLE:
                vTaskDelay(100);
                break;
            default:
                break;
            }
        }
        ESP_ERROR_CHECK(rmt_transmit(led_chan, led_encoder, led_strip_pixels, sizeof(led_strip_pixels), &tx_config));
        ESP_ERROR_CHECK(rmt_tx_wait_all_done(led_chan, portMAX_DELAY));
        vTaskDelay(130);
    }
}

void led_refresh()
{
    ESP_ERROR_CHECK(rmt_transmit(led_chan, led_encoder, led_strip_pixels, sizeof(led_strip_pixels), &tx_config));
}